package com.xinqi.common.redis.topic;

import com.xinqi.common.redis.topic.api.TopicEventListener;
import com.xinqi.common.redis.topic.api.TopicName;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RTopic;
import org.redisson.api.RedissonClient;
import org.redisson.api.listener.MessageListener;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * redisson 订阅发布帮助类
 *
 * @author linkai
 * @date 2023/7/6
 */
@Slf4j
@RequiredArgsConstructor
public class TopicHelp {
    private final RedissonClient redissonClient;
    private final Map<String, RTopic> blockingQueueMap = new ConcurrentHashMap<>();

    /**
     * 获取主题
     *
     * @param topic 主题
     * @return 返回主题对象
     */
    public RTopic getTopic(String topic) {
        return blockingQueueMap.computeIfAbsent(topic, redissonClient::getTopic);
    }

    /**
     * 获取主题通道名称
     *
     * @param topic 主题
     * @return 返回管道名称列表
     */
    public List<String> getChannelNames(TopicName topic) {
        return getChannelNames(topic.topicName());
    }

    /**
     * 获取主题通道名称
     *
     * @param topic 主题
     * @return 返回管道名称列表
     */
    public List<String> getChannelNames(String topic) {
        return getTopic(topic).getChannelNames();
    }

    /**
     * 发送消息
     *
     * @param topic   主题
     * @param message 消息
     * @param <T>     消息类型
     * @return 接收客户端消息数量
     */
    public <T> long publish(TopicName topic, T message) {
        return publish(topic.topicName(), message);
    }

    public <T> long publish(String topic, T message) {
        RTopic rTopic = getTopic(topic);
        return rTopic.publish(message);
    }

    /**
     * 添加消息监听
     *
     * @param listener 监听器
     * @param <T>      消息类型
     * @return 返回唯一监听ID
     */
    public <T> int addListener(TopicEventListener<T> listener) {
        return addListener(listener.topicName(), listener.getMsgType(), listener);
    }

    /**
     * 添加消息监听
     *
     * @param topic    主题
     * @param type     消息类型
     * @param listener 监听器
     * @param <T>      消息类型
     * @return 返回唯一监听ID
     */
    public <T> int addListener(String topic, Class<T> type, MessageListener<T> listener) {
        RTopic rTopic = getTopic(topic);
        return rTopic.addListener(type, listener);
    }
}
